package com.dagit.core.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import com.dagit.core.DMap;
import com.dagit.core.map.proxy.CachedProxyMap;
import com.dagit.core.map.proxy.DirectProxyMap;
import com.dagit.core.map.proxy.ProxyMap;
import com.dagit.core.map.proxy.ProxyType;
import com.dagit.core.map.proxy.ServerProxyMap;

public class MapImpl<K, V> implements DMap<K, V> {

	private ProxyMap<K, V> proxy = null;
	private Map<K, V> local = new ConcurrentHashMap<K, V>();
	private ProxyType proxyType;
	public static ProxyType DEFAULT_PROXY_TYPE = ProxyType.DIRECT_PROXY;

	public MapImpl(Object key){
		this(DEFAULT_PROXY_TYPE,key);
	}
	
	public MapImpl(ProxyType proxyType,Object key){
		this.proxyType = proxyType;
		if (this.proxyType == ProxyType.CACHED_PROXY){
			proxy = new CachedProxyMap<K, V>();//TODO not implemented yet
		}else if (this.proxyType == ProxyType.DIRECT_PROXY){
			proxy = new DirectProxyMap<K, V>(key);
		}else if (this.proxyType == ProxyType.SERVER_CLIENT_PROXY){
			//TODO find proxyType by server client
			proxy = new ServerProxyMap<K, V>();
		}
	}
	
	/////////////              /////////////////////
	@Override
	public int size() {
		return local.size() + proxy.size();
	}

	@Override
	public boolean isEmpty() {
		if (!local.isEmpty()){ /// shortcut
			return false;
		}
		return proxy.isEmpty();
	}

	@Override
	public boolean containsKey(Object key) {
		if (local.containsKey(key)){
			return true;
		}
		return proxy.containsKey(key);
	}

	@Override
	public boolean containsValue(Object value) {
		if (local.containsValue(value)){
			return true;
		}
		return proxy.containsValue(value);
	}

	@Override
	public V get(Object key) {
		if (local.containsKey(key)){
			return local.get(key);
		}
		return proxy.get(key);
	}

	@Override
	public V put(K key, V value) {
		// TODO check statistics then put
		return null;
	}

	@Override
	public V remove(Object key) {
		if (local.containsKey(key)){
			//TODO firstly remove backups
			return local.remove(key);
		}
		return proxy.remove(key);
	}

	@Override
	public void putAll(Map<? extends K, ? extends V> m) {
		// TODO put all map with single signal
		
	}

	@Override
	public void clear() {
		local.clear();
		proxy.clear();
	}

	@Override
	public Set<K> keySet() {
		Set<K> set = new  HashSet<K>();
		set.addAll(local.keySet());
		set.addAll(proxy.keySet());
		return set;
	}

	@Override
	public Collection<V> values() {
		Collection<V> values = new ArrayList<V>();
		values.addAll(local.values());
		values.addAll(proxy.values());
		return values;
	}

	@Override
	public Set<java.util.Map.Entry<K, V>> entrySet() {
		Set<java.util.Map.Entry<K, V>> set = new  HashSet<java.util.Map.Entry<K, V>>();
		set.addAll(local.entrySet());
		set.addAll(proxy.entrySet());
		return set;
	}

	@Override
	public Map<K, V> getLocalMap() {
		return local;
	}
}
